package com.nhim.cms.admin.client.customwidget.ui;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.requestfactory.shared.Receiver;
import com.google.gwt.requestfactory.shared.ServerFailure;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.cellview.client.HasKeyboardPagingPolicy.KeyboardPagingPolicy;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;

import com.nhim.cms.admin.client.rpc.CustomWidgetPropertyService;
import com.nhim.cms.admin.client.rpc.CustomWidgetPropertyServiceAsync;
import com.nhim.cms.admin.client.style.Styles;
import com.nhim.cms.admin.shared.CustomWidgetInstanceProxy;
import com.nhim.cms.admin.shared.CustomWidgetInstanceRequest;
import com.nhim.cms.admin.shared.CustomWidgetPropertyProxy;
import com.nhim.cms.admin.shared.CustomWidgetPropertyValueProxy;
import com.nhim.cms.admin.shared.CustomWidgetPropertyValueRequest;
import com.nhim.cms.admin.shared.CustomWidgetProxy;
import com.nhim.cms.admin.shared.NhimCMSAdminRequestFactory;

public class CustomWidgetInstance extends PopupPanel {

	private static CustomWidgetInstanceUiBinder uiBinder = GWT
			.create(CustomWidgetInstanceUiBinder.class);

	@UiTemplate("CustomWidgetInstance.ui.xml")
	interface CustomWidgetInstanceUiBinder extends
			UiBinder<Widget, CustomWidgetInstance> {
	}

	@UiField
	ScrollablePagerPanel pagerPanel;

	@UiField
	Button btnClose;
	@UiField
	Button btnSave;
	@UiField
	Button btnDelete;
	@UiField
	Button btnNew;
	@UiField
	TextBox txtName;
	@UiField
	TextBox txtDescription;
	@UiField
	HTMLPanel contentPanel;
	@UiField
	VerticalPanel cwgPropertiesPanel;

	private Boolean IsNew = false;
	private CustomWidgetInstanceProxy currentCWIProxy;
	private Map<Integer, CustomWidgetPropertyPanel> propertiesPanelDict = new HashMap<Integer, CustomWidgetPropertyPanel>();
	List<CustomWidgetPropertyValueProxy> currentListCustomWidgetPropertyValueProxy;

	ArrayList<CustomWidgetPropertyProxy> listCustomWidgetProperty;
	/**
	 * The CellList.
	 */
	private CellList<CustomWidgetInstanceProxy> cellList;

	// Add a selection model so we can select cells.
	SingleSelectionModel<CustomWidgetInstanceProxy> selectionModel = new SingleSelectionModel<CustomWidgetInstanceProxy>(
			KEY_PROVIDER);

	private ListDataProvider<CustomWidgetInstanceProxy> dataProvider = new ListDataProvider<CustomWidgetInstanceProxy>();
	private final NhimCMSAdminRequestFactory requestFactory;
	private final CustomWidgetProxy customWidgetProxy;
	private final CustomWidgetPropertyServiceAsync customWidgetPropertyService = GWT
			.create(CustomWidgetPropertyService.class);

	public CustomWidgetInstance(NhimCMSAdminRequestFactory requestFactory,
			CustomWidgetProxy customWidgetProxy) {
		super(false, true);
		requestFactory.customWidgetInstanceRequest();
		this.customWidgetProxy = customWidgetProxy;
		this.requestFactory = requestFactory;
		setWidth("750px");
		setHeight("550px");
		setStyleName(Styles.common().popupPanel());
		add(uiBinder.createAndBindUi(this));
		customWidgetPropertyService.getProperties(
				customWidgetProxy.getClassName(),
				new AsyncCallback<ArrayList<CustomWidgetPropertyProxy>>() {
					public void onFailure(Throwable caught) {
						Window.alert(caught.getMessage());

					}

					public void onSuccess(
							ArrayList<CustomWidgetPropertyProxy> listcwg) {
						listCustomWidgetProperty = listcwg;

					}
				});
		btnDelete.setVisible(false);
		LoadCustomWidgetInstance();
		contentPanel.setVisible(false);

	}

	@UiHandler("btnDelete")
	void handleButtonDeleteClick(ClickEvent e) {
		if (Window.confirm("Are you sure you want to delete!")) {
			try {
				requestFactory.customWidgetInstanceRequest()
						.remove(currentCWIProxy.getId())
						.fire(new Receiver<Boolean>() {

							@Override
							public void onSuccess(Boolean arg0) {
								rebindCustomWidgetInstanceList();

							}
						});
			} catch (Exception ex) {
				Window.alert(ex.getMessage());
			}
		}
	}

	@UiHandler("btnClose")
	void handleButtonCloseClick(ClickEvent e) {
		this.hide();
	}

	@UiHandler("btnSave")
	void handleButtonSaveClick(ClickEvent e) {

		try {
			if (!IsNew) {
				CustomWidgetInstanceRequest thisInstanceRequest = requestFactory
						.customWidgetInstanceRequest();
				currentCWIProxy = thisInstanceRequest.edit(currentCWIProxy);
				IsNew = false;
				currentCWIProxy.setName(txtName.getText());
				currentCWIProxy.setDescription(txtDescription.getText());
				currentCWIProxy.setCustomWidget(customWidgetProxy);
				thisInstanceRequest.persit(currentCWIProxy).fire(
						new Receiver<CustomWidgetInstanceProxy>() {

							@Override
							public void onSuccess(
									CustomWidgetInstanceProxy instance) {
								currentCWIProxy = instance;
								try {
									for (CustomWidgetPropertyValueProxy pProxy : currentListCustomWidgetPropertyValueProxy) {
										CustomWidgetPropertyPanel cwPropertyPanel = propertiesPanelDict
												.get(pProxy.getId());
										CustomWidgetPropertyValueRequest thisRequest = requestFactory
												.customWidgetPropertyValueRequest();
										pProxy = thisRequest.edit(pProxy);
										pProxy.setName(cwPropertyPanel
												.getName());
										pProxy.setDataType(cwPropertyPanel
												.getDataType());
										pProxy.setValue(cwPropertyPanel
												.getValue());
										thisRequest.persit(pProxy).fire();
									}

									rebindCustomWidgetInstanceList();
									selectionModel.setSelected(instance, true);
								} catch (Exception ex) {
									Window.alert(ex.getMessage());
								}

							}
						});

			} else {
				CustomWidgetInstanceRequest instanceRequest = requestFactory
						.customWidgetInstanceRequest();
				CustomWidgetInstanceProxy thisCWIProxy = instanceRequest
						.create(CustomWidgetInstanceProxy.class);
				thisCWIProxy.setName(txtName.getText());
				thisCWIProxy.setDescription(txtDescription.getText());
				thisCWIProxy.setCustomWidget(customWidgetProxy);

				instanceRequest.persit(thisCWIProxy).fire(
						new Receiver<CustomWidgetInstanceProxy>() {

							@Override
							public void onSuccess(
									CustomWidgetInstanceProxy instance) {

								try {
									currentCWIProxy = instance;
									for (CustomWidgetPropertyPanel cwPropertyPanel : propertiesPanelDict
											.values()) {
										CustomWidgetPropertyValueRequest thisRequest = requestFactory
												.customWidgetPropertyValueRequest();
										CustomWidgetPropertyValueProxy cwPropertyValue = thisRequest
												.create(CustomWidgetPropertyValueProxy.class);
										cwPropertyValue.setName(cwPropertyPanel
												.getName());
										cwPropertyValue
												.setDataType(cwPropertyPanel
														.getDataType());
										cwPropertyValue
												.setValue(cwPropertyPanel
														.getValue());
										cwPropertyValue
												.setCustomWidgetInstance(instance);
										thisRequest.persit(cwPropertyValue)
												.fire();
									}
									rebindCustomWidgetInstanceList();
									selectionModel.setSelected(instance, true);
								} catch (Exception ex) {
									Window.alert(ex.getMessage());
								}

							}
						});

			}

			Window.alert("CustomWidgetInstance was created sucessfully!");
		} catch (Exception ex) {
			Window.alert(ex.getMessage());
		}

	}

	@UiHandler("btnNew")
	void handleButtonAddTemplateClick(ClickEvent e) {
		contentPanel.setVisible(true);
		btnDelete.setVisible(false);
		IsNew = true;
		txtName.setText("");
		txtDescription.setText("");
		propertiesPanelDict.clear();
		cwgPropertiesPanel.clear();
		int i = 0;
		for (CustomWidgetPropertyProxy cwg : listCustomWidgetProperty) {
			CustomWidgetPropertyPanel panel = new CustomWidgetPropertyPanel(
					cwg, "");
			cwgPropertiesPanel.add(panel);
			propertiesPanelDict.put(i, panel);
			i++;
		}

	}

	/**
	 * The key provider that provides the unique ID of a contentType.
	 */
	public static final ProvidesKey<CustomWidgetInstanceProxy> KEY_PROVIDER = new ProvidesKey<CustomWidgetInstanceProxy>() {
		public Object getKey(CustomWidgetInstanceProxy item) {
			return item == null ? null : item.getId();
		}
	};

	private void LoadCustomWidgetInstance() {
		// Create a CellList.
		CustomWidgetInstanceCell customWidgetInstanceCell = new CustomWidgetInstanceCell(
				Styles.resources().customWidgetInstance());

		// Set a key provider that provides a unique key for each
		// CustomWidgetInstance. If key is
		// used to identify CustomWidgetInstances when fields (such as the name
		// and description)
		// change.
		cellList = new CellList<CustomWidgetInstanceProxy>(
				customWidgetInstanceCell, KEY_PROVIDER);
		cellList.setPageSize(30);
		cellList.setKeyboardPagingPolicy(KeyboardPagingPolicy.INCREASE_RANGE);
		cellList.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.BOUND_TO_SELECTION);

		cellList.setSelectionModel(selectionModel);
		selectionModel
				.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
					public void onSelectionChange(SelectionChangeEvent event) {
						IsNew = false;
						currentCWIProxy = selectionModel.getSelectedObject();
						try {
							propertiesPanelDict.clear();
							cwgPropertiesPanel.clear();
							contentPanel.setVisible(true);
							btnDelete.setVisible(true);
							txtName.setText(currentCWIProxy.getName());
							txtDescription.setText(currentCWIProxy
									.getDescription());
							for (final CustomWidgetPropertyProxy cwg : listCustomWidgetProperty) {
								requestFactory
										.customWidgetPropertyValueRequest()
										.findByCustomWidgetInstanceId(
												currentCWIProxy.getId())
										.fire(new Receiver<List<CustomWidgetPropertyValueProxy>>() {

											@Override
											public void onSuccess(
													List<CustomWidgetPropertyValueProxy> listPropertyValue) {

												currentListCustomWidgetPropertyValueProxy = listPropertyValue;
												for (CustomWidgetPropertyValueProxy pProxy : listPropertyValue) {
													if (cwg.getName()
															.equalsIgnoreCase(
																	pProxy.getName())) {
														CustomWidgetPropertyPanel panel = new CustomWidgetPropertyPanel(
																cwg,
																pProxy.getValue());
														cwgPropertiesPanel
																.add(panel);
														propertiesPanelDict.put(
																pProxy.getId(),
																panel);
													}
												}

											}
										});

							}
						} catch (Exception ex) {
							Window.alert(ex.getMessage());
						}

					}
				});
		contentPanel.setVisible(true);

		pagerPanel.setDisplay(cellList);
		dataProvider.addDataDisplay(cellList);
		final List<CustomWidgetInstanceProxy> data = dataProvider.getList();
		requestFactory.customWidgetInstanceRequest()
				.getByCustomWidgetId(customWidgetProxy.getId())
				.fire(new Receiver<List<CustomWidgetInstanceProxy>>() {
					@Override
					public void onFailure(ServerFailure error) {
						Window.alert("There was an error while fetching CustonWidgetInstance.");
					}

					@Override
					public void onSuccess(
							List<CustomWidgetInstanceProxy> results) {
						data.clear();
						data.addAll(results);
					}
				});
		cellList.redraw();
	}

	private void rebindCustomWidgetInstanceList() {
		final List<CustomWidgetInstanceProxy> data = dataProvider.getList();
		data.clear();
		requestFactory.customWidgetInstanceRequest()
				.getByCustomWidgetId(customWidgetProxy.getId())
				.fire(new Receiver<List<CustomWidgetInstanceProxy>>() {
					@Override
					public void onFailure(ServerFailure error) {
						Window.alert("There was an error while fetching CustonWidgetInstance.");
					}

					@Override
					public void onSuccess(
							List<CustomWidgetInstanceProxy> results) {
						data.clear();
						data.addAll(results);
					}
				});
		cellList.redraw();

	}

	/**
	 * The Cell used to render a {@link CustomWidgetInstance}.
	 */
	static class CustomWidgetInstanceCell extends
			AbstractCell<CustomWidgetInstanceProxy> {

		/**
		 * The html of the image used for contacts.
		 */
		private final String imageHtml;

		public CustomWidgetInstanceCell(ImageResource image) {
			this.imageHtml = AbstractImagePrototype.create(image).getHTML();
		}

		@Override
		public void render(com.google.gwt.cell.client.Cell.Context arg0,
				CustomWidgetInstanceProxy value, SafeHtmlBuilder sb) {

			// Value can be null, so do a null check..
			if (value == null) {
				return;
			}

			sb.appendHtmlConstant("<table>");

			// Add the content type image.
			sb.appendHtmlConstant("<tr><td rowspan='3'>");
			sb.appendHtmlConstant(imageHtml);
			sb.appendHtmlConstant("</td>");

			// Add the name and description.
			sb.appendHtmlConstant("<td style='font-size:95%;'>");
			sb.appendEscaped(value.getName());
			sb.appendHtmlConstant("</td></tr><tr><td style='text-align: right; font-style: italic; color: #666666;'>");
			sb.appendEscaped(value.getDescription());
			sb.appendHtmlConstant("</td></tr></table>");
		}

	}

}
